package com.vonchenchen.android_renderer;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Canvas;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.SurfaceView;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.RelativeLayout;
import android.widget.SeekBar;

import com.vonchenchen.renderer.FileDataProvider;
import com.vonchenchen.renderer.FrameRenderer;
import com.vonchenchen.renderer.RendererCanvas;
import com.vonchenchen.test.SystemHelper;

import java.io.File;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "renderer_MainActivity";

    private static final int TEST_WIDNOW_NUM = 20;

//    private FrameRenderer mRenderer;
//    private SurfaceView mSurfaceView;
//    private FileDataProvider mFileDataProvider;

    private ScheduledExecutorService mScheduledExecutorService;

    private boolean mStartPlay;
    private SeekBar mSeekBar;
    private RelativeLayout mMainLayout;

    private SurfaceView[] mSurfaceViews;
    FrameRenderer[] renderers;
    FileDataProvider[] providers;

    private RelativeLayout[] mLayouts;
    private SurfaceView[] mDySurfaceViews;
    FrameRenderer[] mDyRenderers;
    FileDataProvider[] mDyProviders;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mSurfaceViews = new SurfaceView[20];
        renderers = new FrameRenderer[20];
        providers = new FileDataProvider[20];
        mSurfaceViews[0] = findViewById(R.id.sv_test1);
        mSurfaceViews[1] = findViewById(R.id.sv_test2);
        mSurfaceViews[2] = findViewById(R.id.sv_test3);
        mSurfaceViews[3] = findViewById(R.id.sv_test4);
        mSurfaceViews[4] = findViewById(R.id.sv_test5);
        mSurfaceViews[5] = findViewById(R.id.sv_test6);
        mSurfaceViews[6] = findViewById(R.id.sv_test7);
        mSurfaceViews[7] = findViewById(R.id.sv_test8);
        mSurfaceViews[8] = findViewById(R.id.sv_test9);
        mSurfaceViews[9] = findViewById(R.id.sv_test10);
        mSurfaceViews[10] = findViewById(R.id.sv_test11);
        mSurfaceViews[11] = findViewById(R.id.sv_test12);
        mSurfaceViews[12] = findViewById(R.id.sv_test13);
        mSurfaceViews[13] = findViewById(R.id.sv_test14);
        mSurfaceViews[14] = findViewById(R.id.sv_test15);
        mSurfaceViews[15] = findViewById(R.id.sv_test16);
        mSurfaceViews[16] = findViewById(R.id.sv_test17);
        mSurfaceViews[17] = findViewById(R.id.sv_test18);
        mSurfaceViews[18] = findViewById(R.id.sv_test19);
        mSurfaceViews[19] = findViewById(R.id.sv_test20);

        mLayouts = new RelativeLayout[10];
        mLayouts[0] = findViewById(R.id.rl_test1);
        mLayouts[1] = findViewById(R.id.rl_test2);
        mLayouts[2] = findViewById(R.id.rl_test3);
        mLayouts[3] = findViewById(R.id.rl_test4);
        mLayouts[4] = findViewById(R.id.rl_test5);
        mLayouts[5] = findViewById(R.id.rl_test6);
        mLayouts[6] = findViewById(R.id.rl_test7);
        mLayouts[7] = findViewById(R.id.rl_test8);
        mLayouts[8] = findViewById(R.id.rl_test9);
        mLayouts[9] = findViewById(R.id.rl_test10);

        findViewById(R.id.btn_createtRender).setOnClickListener((v)->{
            createRenderer();
        });

        findViewById(R.id.btn_destoryRender).setOnClickListener((v)->{
            deleteRenderer();
        });

        findViewById(R.id.btn_trigger).setOnClickListener((v)->{
            startTrigger();
        });

        mSeekBar = findViewById(R.id.sb_scale);
        mSeekBar.setMax(100);
        mSeekBar.setProgress(100);
        mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                int maxW = mMainLayout.getWidth();
                int maxH = mMainLayout.getHeight();
                int surfaceW = (int)( maxW * ((double)progress)/100 );
                int surfaceH = (int)( maxH * ((double)progress)/100 );
                ViewGroup.LayoutParams params = mSurfaceViews[0].getLayoutParams();
                params.width = surfaceW;
                params.height = surfaceH;
                mSurfaceViews[0].setLayoutParams(params);
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {

            }
        });

        findViewById(R.id.btn_looptest).setOnClickListener((v)->{

            new Thread(new Runnable() {
                @Override
                public void run() {

                    boolean startTrigger = false;

                    while(true) {

                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }

                        createRenderer();
                        if(!startTrigger){
                            startTrigger();
                            startTrigger = true;
                        }

                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }

                        deleteRenderer();
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }

                        moveTaskToBack(true);
                        //deleteRenderer();

                        try {
                            Thread.sleep(500);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        SystemHelper.setTopApp(MainActivity.this);
                    }
                }
            }).start();
        });

        findViewById(R.id.btn_backtest).setOnClickListener((v)->{
            Intent intent = new Intent();
            intent.setAction("com.vonchenchen.renderer");
            sendBroadcast(intent);
        });

        initReceiver();
    }

    private void createRenderer(){

        //startTestRenderer();
        //createRenderer2();
        createRenderer3();
    }

    /**
     * 测试每次创建新的surfaceview
     */
    private void createRenderer2(){

        mDySurfaceViews = new SurfaceView[10];
        mDyRenderers = new FrameRenderer[10];
        mDyProviders = new FileDataProvider[10];

        runOnUiThread(()->{
            for(int i=0; i<10; i++) {
                mDySurfaceViews[i] = new SurfaceView(MainActivity.this);
                mLayouts[i].addView(mDySurfaceViews[i]);
            }
        });

        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        for(int i=0; i<10; i++){

            mDyRenderers[i] = new FrameRenderer();
            RendererCanvas canvas = new RendererCanvas(mDySurfaceViews[i]);
            mDyRenderers[i].setCanvas(canvas);
            mDyProviders[i] = new FileDataProvider();
            mDyProviders[i].registerRenderer(mDyRenderers[i]);

            File file = getCacheDir();
            String path = file.getAbsoluteFile()+"/bus_cif.y4m";
            //mDyProviders[i].initProvider("/sdcard/bus_cif.y4m");
            mDyProviders[i].initProvider(path);
        }
    }

    private void startTrigger(){
        if(!mStartPlay) {
            if (mScheduledExecutorService != null) {
                mScheduledExecutorService.shutdown();
                mScheduledExecutorService = null;
            }
            mScheduledExecutorService = Executors.newScheduledThreadPool(1);
            //triger provider provide next frame
            mScheduledExecutorService.scheduleAtFixedRate(() -> {

//                for(int i=0; i<TEST_WIDNOW_NUM; i++){
//                    providers[i].provideNextFrame();
//                }

                if(mDyProviders.length == 10) {
                    for (int i = 0; i < 10; i++) {
                        if (mDyProviders[i] != null) {
                            mDyProviders[i].provideNextFrame();
                        }
                    }
                }

            }, 0, 30, TimeUnit.MILLISECONDS);
        }else{
            if (mScheduledExecutorService != null) {
                mScheduledExecutorService.shutdown();
                mScheduledExecutorService = null;
            }
        }
        mStartPlay = !mStartPlay;
    }

    private void deleteRenderer(){

        //stopTestRenderer();
        //deleteRenderer2();
        deleteRenderer3();
    }

    private void deleteRenderer2(){
        for(int i=0; i<10; i++){
            mDyProviders[i].release();
            mDyProviders[i] = null;
            mDyRenderers[i].release();
            mDyRenderers[i] = null;
        }

        runOnUiThread(()->{
            for(int i=0; i<10; i++) {
                mLayouts[i].removeAllViews();
            }
        });

        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private void startTestRenderer(){

        for(int i=0; i<TEST_WIDNOW_NUM; i++){
            renderers[i] = new FrameRenderer();
            RendererCanvas canvas = new RendererCanvas(mSurfaceViews[i]);
            renderers[i].setCanvas(canvas);
            providers[i] = new FileDataProvider();
            providers[i].registerRenderer(renderers[i]);
            providers[i].initProvider("/sdcard/bus_cif.y4m");
        }
    }

    private void stopTestRenderer(){

        for(int i=0; i<TEST_WIDNOW_NUM; i++){
            providers[i].release();
            renderers[i].release();
        }
    }

    private void createRenderer3(){

        if(mDySurfaceViews == null) {
            mDySurfaceViews = new SurfaceView[10];
        //}
            runOnUiThread(()->{
                for(int i=0; i<10; i++) {
                    mDySurfaceViews[i] = new SurfaceView(MainActivity.this);
                    mLayouts[i].addView(mDySurfaceViews[i]);
                }
            });
        }

        mDyRenderers = new FrameRenderer[10];
        mDyProviders = new FileDataProvider[10];

        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

//        for(int i=0; i<10; i++) {
//            final int tmp = i;
//            runOnUiThread(() -> {
//                mDySurfaceViews[tmp].requestLayout();
//            });
//        }

        for(int i=0; i<10; i++){

            mDyRenderers[i] = new FrameRenderer();
            RendererCanvas canvas = new RendererCanvas(mDySurfaceViews[i]);
            mDyRenderers[i].setCanvas(canvas);
            mDyProviders[i] = new FileDataProvider();
            mDyProviders[i].registerRenderer(mDyRenderers[i]);

            File file = getCacheDir();
            String path = file.getAbsoluteFile()+"/bus_cif.y4m";
            mDyProviders[i].initProvider(path);
            //mDyProviders[i].initProvider("/sdcard/bus_cif.y4m");
        }
    }

    private void deleteRenderer3(){
        for(int i=0; i<10; i++){
            mDyProviders[i].release();
            mDyProviders[i] = null;
            mDyRenderers[i].release();
            mDyRenderers[i] = null;
        }

//        runOnUiThread(()->{
//            for(int i=0; i<10; i++) {
//                mLayouts[i].removeAllViews();
//            }
//        });

        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        deinitReceiver();
    }

    private InternalReceiver mInternalReceiver;
    private boolean mIsForground;

    @Override
    protected void onResume() {
        super.onResume();
        mIsForground = true;
    }

    @Override
    protected void onPause() {
        super.onPause();
        mIsForground = false;
    }

    @Override
    protected void onStop() {
        super.onStop();
    }

    private Handler mHandler = new Handler(){
        @Override
        public void handleMessage(@NonNull Message msg) {

            if(mIsForground){
                moveTaskToBack(true);
                Log.i(TAG, "back...");
            }else {
                SystemHelper.setTopApp(MainActivity.this);
                Log.i(TAG, "forgound...");
            }

            if (mHandler != null) {
                Message reMsg = new Message();
                reMsg.what = msg.what;
                reMsg.arg1 = msg.arg1;
                mHandler.sendMessageDelayed(reMsg, reMsg.arg1);
            }
        }
    };

    private static final String BROAD_CAST_BACK = "com.vonchenchen.renderer";

    void initReceiver(){

        if(mInternalReceiver == null){
            IntentFilter intentfilter = new IntentFilter();
            intentfilter.addAction(BROAD_CAST_BACK);
            mInternalReceiver = new InternalReceiver();
            registerReceiver(mInternalReceiver, intentfilter);
        }
    }

    void deinitReceiver(){
        if(mInternalReceiver != null) {
            unregisterReceiver(mInternalReceiver);
            mInternalReceiver = null;
        }
    }

    private class InternalReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {

            if (BROAD_CAST_BACK.equals(intent.getAction())){
                mHandler.removeMessages(1);
                Message msg = new Message();
                msg.arg1 = 1000;
                msg.what = 1;
                mHandler.sendMessageDelayed(msg, 1000);
            }
        }
    }

    //bruteforce test renderer
    //adb shell am broadcast -a com.vonchenchen.renderer
}